package com.pencilisland.pay.mgt.console.service.impl;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.pencilisland.pay.mgt.console.bean.ConstantVars;
import com.pencilisland.pay.mgt.console.entity.SysOrg;
import com.pencilisland.pay.mgt.console.entity.SysUser;
import com.pencilisland.pay.mgt.console.entity.SysUser_;
import com.pencilisland.pay.mgt.console.repository.UserRepository;
import com.pencilisland.pay.mgt.console.service.FileSystemService;
import com.pencilisland.pay.mgt.console.service.OrgService;
import com.pencilisland.pay.mgt.console.service.UserService;
import com.pencilisland.pay.mgt.console.shiro.ShiroUser;

@Component
public class UserServiceImpl implements UserService {

	Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	UserRepository userRepo;
	@Autowired
	OrgService orgService;
	@Autowired
	FileSystemService fileSystemService;

	@Override
	public Page<SysUser> userList(final SysUser cretiria, int start, int limit) {
		Specification<SysUser> spec = new Specification<SysUser>() {

			@Override
			public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				if (!StringUtils.isEmpty(cretiria.getUserName())) {
					list.add(cb.like(root.get(SysUser_.userName), "%" + cretiria.getUserName() + "%"));
				}
				if (!StringUtils.isEmpty(cretiria.getUserNumber())) {
					list.add(cb.like(root.get(SysUser_.userNumber), "%" + cretiria.getUserNumber() + "%"));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.ASC, SysUser_.userCode.getName()));

		Pageable pageable = new PageRequest(start / limit, limit, sort);

		return userRepo.findAll(spec, pageable);
	}

	@Override
	public SysUser save(SysUser user) {
		if (user.getUserId() == null) {
			user.setStatus("0");
			user.setPassword(new Md5Hash(user.getPassword()).toBase64());
			user.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));

		} else {
			SysUser updateUser = userRepo.findOne(user.getUserId());
			if (updateUser == null) {
				log.info("没有找到要更新的用户【{}】", user.getUserId());
				return null;
			}
			user.setPassword(updateUser.getPassword());
			user.setStatus(updateUser.getStatus());
		}

		List<SysOrg> orgList = orgService.findAllParentOrg(user);
		if (orgList != null && !orgList.isEmpty()) {
			StringBuilder orgIds = new StringBuilder();
			StringBuilder orgNames = new StringBuilder();
			for (int i = orgList.size() - 1; i >= 0; i--) {
				SysOrg org = orgList.get(i);
				if ("root".equals(org.getOrgCode())) {
					continue;
				}

				if (orgIds.length() == 0) {
					orgIds.append(org.getOrgId());
					orgNames.append(org.getOrgName());
				} else {
					orgIds.append("/").append(org.getOrgId());
					orgNames.append("/").append(org.getOrgName());
				}
			}

			user.setOrgIdPath(orgIds.toString());
			user.setOrgNamePath(orgNames.toString());
		}

		return userRepo.save(user);
	}

	@Override
	public SysUser loadData(Long id) {
		return userRepo.findOne(id);
	}

	@Override
	public void delete(Long id) {
		userRepo.delete(id);
	}

	@Override
	public SysUser findByLoginName(String loginName) {
		return userRepo.findByLoginName(loginName);
	}

	@Override
	public SysUser findSessionUser() {
		ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getSession()
				.getAttribute(ConstantVars.SESSION_SHIRO_USER);
		return (SysUser) shiroUser.getRealUser();
	}

	@Override
	public void modifyPassword(Long userId, String oldPassword, String newPassword, String newPasswordConfirm)
			throws Exception {
		if (!newPassword.equals(newPasswordConfirm)) {
			log.info("修改用户[{}]密码->确认密码不对", userId);
			throw new Exception("确认密码不对");
		}

		SysUser user = userRepo.findOne(userId);
		if (user == null) {
			log.info("修改用户[{}]密码->用户不存在", userId);
			throw new Exception("用户不存在");
		}

		String oldPasswordConfirm = new Md5Hash(oldPassword).toBase64();

		if (!user.getPassword().equals(oldPasswordConfirm)) {
			log.info("修改用户[{}]密码->原密码不对", userId);
			throw new Exception("原密码不对");
		}

		user.setPassword(new Md5Hash(newPassword).toBase64());

		userRepo.save(user);

	}

	@Override
	public void uploadAvatar(MultipartFile file) throws Exception {
		SysUser user = findSessionUser();
		StringBuilder pathBuilder = new StringBuilder();
		pathBuilder.append("user").append(File.separator).append(user.getUserId());
		String fileName = "avatar.jpg";

		log.info("更新用户[{}]头像", user.getUserId());

		fileSystemService.createFile(pathBuilder.toString(), fileName, file);
	}

	@Override
	public byte[] avatar() {
		SysUser user = findSessionUser();
		StringBuilder pathBuilder = new StringBuilder();
		pathBuilder.append("user").append(File.separator).append(user.getUserId());
		String fileName = "avatar.jpg";

		log.info("获取用户[{}]头像", user.getUserId());

		File avatar = fileSystemService.getFile(pathBuilder.toString(), fileName);

		if (avatar.exists()) {
			try {
				return FileCopyUtils.copyToByteArray(avatar);
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			try {
				avatar = new File(System.getProperty("web.root"), "resources/app/image/icon.png");
				return FileCopyUtils.copyToByteArray(avatar);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return null;
	}

	@Override
	public void resetPassword(Long userId) {
		log.info("重置用户【{}】密码", userId);
		SysUser user = userRepo.findOne(userId);
		user.setPassword(new Md5Hash("888888").toBase64());
		userRepo.save(user);
	}

}
